package org.kernely.log;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogListener;
import org.osgi.service.log.LogReaderService;
import org.osgi.service.log.LogService;

import com.vaadin.Application;
import com.vaadin.terminal.Sizeable;
import com.vaadin.terminal.gwt.server.AbstractApplicationServlet;
import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Panel;
import com.vaadin.ui.Table;
import com.vaadin.ui.Window;
public class LogApplication extends Application implements LogListener{
	
	private FormLayout mainLayout;
	private Window main;
	private Table logTable;
	private HorizontalLayout checkLayout;
	private CheckBox checkInfo;
	private CheckBox checkDebug;
	private CheckBox checkWarning;
	private CheckBox checkError;
	private static LogReaderService logservice;
	
	public static class VaadinLogServlet extends AbstractApplicationServlet {

		/**
		 * 
		 */
		private static final long serialVersionUID = 102610594159015L;

		@Override
		protected Class getApplicationClass() {
			return LogApplication.class;
		}

		@Override
		protected Application getNewApplication(HttpServletRequest request)
		throws ServletException {
			return new LogApplication();
		}

	}

	@Override
	public void init() {
		logservice.addLogListener(this);
		main = new Window("Kernely: Log");
		mainLayout = new FormLayout();
		Panel panel = new Panel();
		main.setContent(panel);
		setMainWindow(main);
		mainLayout.setSizeFull();
		
		panel.setHeight(100, Sizeable.UNITS_PERCENTAGE);
		
		logTable = new Table();

		logTable.setSizeFull();
		logTable.setPageLength(0);
		logTable.setHeight(100, Sizeable.UNITS_PERCENTAGE);
		logTable.addContainerProperty("Date", String.class, null);
		logTable.addContainerProperty("Log level", String.class,  null);
		logTable.addContainerProperty("Logged by", String.class, null);
		logTable.addContainerProperty("Message",  String.class,  null);
		
		logTable.setColumnWidth("Log level", 100);
		logTable.setColumnWidth("Date", 140);
		logTable.setColumnWidth("Logged by", 200);

		checkInfo = new LogCheckBox("Display \"INFO\" logs", true);
		checkDebug = new LogCheckBox("Display \"DEBUG\" logs", true);
		checkWarning = new LogCheckBox("Display \"WARNING\" logs", true);
		checkError = new LogCheckBox("Display \"ERROR\" logs", true);
	
		checkLayout = new HorizontalLayout();
		checkLayout.addComponent(checkInfo);
		checkLayout.addComponent(checkDebug);
		checkLayout.addComponent(checkWarning);
		checkLayout.addComponent(checkError);

		listLog();

		panel.addComponent(checkLayout);
		panel.addComponent(new RefreshButton());
		panel.addComponent(logTable);
	}
	
	private class LogCheckBox extends CheckBox{
		private static final long serialVersionUID = -5754594621339389249L;
		public LogCheckBox(String caption,boolean defaultValue){
			this.setCaption(caption);
			this.setValue(defaultValue);
			this.setImmediate(true);
			this.addListener(new ValueChangeListener(){
				private static final long serialVersionUID = -2761797639733607828L;

				@Override
				public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) {
					listLog();
				}
				
			});
		}
	}
	
	private class RefreshButton extends CustomComponent implements Button.ClickListener {
		private static final long serialVersionUID = -7556811745471098708L;
		private Button refreshButton;
		
		//Create the button
		public RefreshButton() {
			refreshButton = new Button("Refresh Logs");
			// Listen for ClickEvents.
			refreshButton.addListener(this);
			setCompositionRoot(refreshButton);
		}

		/** Handle click events for the button. */
		public void buttonClick (Button.ClickEvent event) {
			listLog();
		}

	}

	
	
	private void listLog(){
		boolean info = ((Boolean) checkInfo.getValue()).booleanValue();
		boolean warning = ((Boolean) checkWarning.getValue()).booleanValue();
		boolean debug = ((Boolean) checkDebug.getValue()).booleanValue();
		boolean error = ((Boolean) checkError.getValue()).booleanValue();
		logTable.removeAllItems();
		Enumeration<LogEntry> latestLogs = logservice.getLog();
		
		int i = 1;
		boolean display = false;
		while(latestLogs.hasMoreElements()){
			LogEntry e = latestLogs.nextElement();
			String level;
			switch(e.getLevel()){
				case LogService.LOG_INFO:
					level = "INFO";
					display = info;
					break;
				case LogService.LOG_WARNING :
					level = "WARNING";
					display = warning;
					break;
				case LogService.LOG_DEBUG:
					level = "DEBUG";
					display = debug;
					break;
				case LogService.LOG_ERROR:
					level = "ERROR";
					display = error;
					break;
				default :
					level = "UNKNOWN";
			}
			if (display){
				Date d = new Date(e.getTime());
				DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy - HH:mm:ss");
				logTable.addItem(new Object[] {dateFormat.format(d), level, e.getBundle().getSymbolicName(), e.getMessage()}, Integer.valueOf(i));
				i++;
			}
		}
		
	}

	@Override
	public void logged(LogEntry entry) {
		//TODO to actualize when there is a new Log.
	}
	
	/**
	 * Gets the log service.
	 * @return the log service
	 */
	public static LogReaderService getLogservice() {
		return logservice;
	}

	/**
	 * Sets the log service.
	 * @param logservice The log service to set.
	 */
	public static void setLogservice(LogReaderService logservice) {
		LogApplication.logservice = logservice;
	}	
}
